package dbTools.pojo.structure.writer.writers;

import dbTools.pojo.structure.BeanSubject;
import dbTools.pojo.structure.property.BeanProperty;
import dbTools.pojo.structure.writer.IWriter;
import dbTools.util.FileUtil;

public class SimpleWriter implements IWriter{

	@Override
	public void doWriterBean(BeanSubject bean) {
		
		FileUtil file= new FileUtil(bean.getPath(),bean.getFileName()+".java");
		
		file.write(getSource(bean));

	}
	
	private String getSource(BeanSubject bean)
	{
		StringBuffer source=new StringBuffer();
		
		//package
		source.append("package "+bean.getPackageStr()+";\r\n\r\n");
		
		//import
		if(bean.getImportItems()!=null)
		{
			for(String importItem : bean.getImportItems())
			{
				source.append("import "+importItem+";\r\n");	
			}
		}
		
		source.append("\r\n");
		
		source.append("public class "+bean.getFileName()+" implements java.io.Serializable { \r\n\r\n");	
		
		source.append(getMainSource(bean));
		
		source.append("}");	
		
		return source.toString();
	}
	
	private String getMainSource(BeanSubject bean)
	{
		StringBuffer source=new StringBuffer();
		
		//fileds
		for(BeanProperty property: bean.getPropertys())
		{
			source.append("	//"+property.getNote()+"\r\n");	
			source.append("	private "+property.getTypeStr()+" "+property.getName()+";\r\n");	
		}
		source.append("\r\n");
		
		// Constructors
		source.append(getConstructors(bean));

		//get set
		source.append("	//Property accessors\r\n");	
		for(BeanProperty property: bean.getPropertys())
		{
			if(property.isGet())
			{
				source.append(getGetMethod(property));
			}
			if(property.isSet())
			{
				source.append(getSetMethod(property));
			}
		}
		
		if(bean.isId())
		{
			source.append(getEqualsMethod(bean));
			source.append(getHashCodeMethod(bean));
		}
		
		return source.toString();
	}
	
	private String getEqualsMethod(BeanSubject bean) {
		StringBuffer source=new StringBuffer();
		
		String idName=bean.getFileName();
		
		source.append("	public boolean equals(Object other) {\r\n");
		source.append("		if ((this == other))\r\n");
		source.append("			return true;\r\n");
		source.append("		if ((other == null))\r\n");
		source.append("			return false;\r\n");
		source.append("		if (!(other instanceof "+idName+"))\r\n");
		source.append("			return false;\r\n\r\n");
		
		source.append("		"+idName+" castOther = ("+idName+") other;\r\n\r\n");
		
		source.append("		return ");
		
		for (int i = 0; i < bean.getPropertys().size(); i++) 
		{
			BeanProperty property = bean.getPropertys().get(i);
			if (i == 0) 
			{
				source.append(GetEqualsItem(property));
			}
			else
			{
				source.append("			&& "+GetEqualsItem(property));
			}
		}
		source.append(";");
		source.append("	}\r\n\r\n");	
		
		return source.toString();
	}
	
	private String GetEqualsItem(BeanProperty property)
	{
		StringBuffer source=new StringBuffer();
		
		String methodName= property.getName().substring(0,1).toUpperCase()+ property.getName().substring(1);
		
		source.append("((this.get"+methodName+"() ==  castOther.get"+methodName+"())\r\n");
		source.append("				||(this.get"+methodName+"()!=null && castOther.get"+methodName+"() !=null \r\n");
		source.append("					&& castOther.get"+methodName+"() !=null \r\n");
		source.append("					&& this.get"+methodName+"().equals(castOther.get"+methodName+"())))\r\n");
		
		return source.toString();
	}
	
	private String getHashCodeMethod(BeanSubject bean) {
		StringBuffer source=new StringBuffer();
		
		source.append("	public int hashCode() {\r\n");
		source.append("		int result = 17;\r\n\r\n");
		
		for (int i = 0; i < bean.getPropertys().size(); i++) 
		{
			BeanProperty property = bean.getPropertys().get(i);
			source.append(GetHashCodeItem(property));
		}
		
		source.append("		return result;\r\n");
		source.append("	}\r\n\r\n");	
		
		return source.toString();
	}
	
	private String GetHashCodeItem(BeanProperty property)
	{
		StringBuffer source=new StringBuffer();
		
		String methodName= property.getName().substring(0,1).toUpperCase()+ property.getName().substring(1);
		
		source.append("		result = 37 * result\r\n");
		source.append("				+ (get"+methodName+"() == null ? 0 : this.get"+methodName+"().hashCode());\r\n");
		
		return source.toString();
	}

	private String getConstructors(BeanSubject bean) {
		StringBuffer source=new StringBuffer();
		
		//empty Constructors
		source.append("	/** default constructor */\r\n");	
		source.append("	public "+bean.getFileName()+"(){\r\n");	
		source.append("\r\n");	
		source.append("	}\r\n\r\n");	
		
		if(bean.getId()!=null)
		{
			//id Constructors
			source.append("	/** minimal constructor */\r\n");	
			source.append("	public "+bean.getFileName()+"("+bean.getId().getFileName()+" id"+"){\r\n");	
			source.append("		this.id = id;\r\n");	
			source.append("	}\r\n\r\n");	
		}
		
		//full Constructors
		if(bean.getPropertys().size()>1)
		{
			source.append("	/** full constructor */\r\n");	
			source.append("	public "+bean.getFileName()+"("+getFullProperty(bean)+"){\r\n");	
			for(BeanProperty property: bean.getPropertys())
			{
				source.append("		this."+property.getName()+" = "+property.getName()+";\r\n");	
			}
			source.append("	}\r\n\r\n");	
		}

		return source.toString();
	}
	
	private String getFullProperty(BeanSubject bean)
	{
       StringBuffer source=new StringBuffer();
		
       for(int i=0; i<bean.getPropertys().size();i++)
       {
    	   BeanProperty property=bean.getPropertys().get(i);
    	   if(i==0)
    	   {
    		   source.append(property.getTypeStr()+" "+property.getName());
    	   }
    	   else
    	   {
    		   if(i%3==0)
    		   {
    			   source.append("\r\n			");	
    		   }
    		   source.append(","+property.getTypeStr()+" "+property.getName());
    	   }
       }
		
		return source.toString();
	}
	

	private String getGetMethod(BeanProperty property) {
		StringBuffer source=new StringBuffer();
		
		String methodName= property.getName().substring(0,1).toUpperCase()+ property.getName().substring(1);
		source.append("	public "+property.getTypeStr()+" get"+methodName+ "(){\r\n");	
		source.append("		return this."+property.getName()+";\r\n");	
		source.append("	}\r\n\r\n");	
		
		return source.toString();
	}
	
	private String getSetMethod(BeanProperty property) {
		StringBuffer source=new StringBuffer();
		
		String methodName= property.getName().substring(0,1).toUpperCase()+ property.getName().substring(1);
		source.append("	public void set"+methodName+ "("+property.getTypeStr()+" "+property.getName()+"){\r\n");	
		source.append("		this."+property.getName()+"="+property.getName()+";\r\n");	
		source.append("	}\r\n\r\n");	
		
		return source.toString();
	}

}
